#ifndef _BASE_HPP_20120407
#define _BASE_HPP_20120407

#include <assert.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#include <malloc.h>
#include <fcntl.h>
#include <stddef.h>

#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/epoll.h>

#include <iostream>
#include <sstream>
#include <algorithm>
#include <functional>
#include <ext/hash_map>

#include <string>

using namespace std;
using namespace __gnu_cxx;

extern int errno;

namespace mina
{
	enum
	{
		READ_EVENT    = 0x1,
		WRITE_EVENT   = 0x2,
		ERROR_EVENT   = 0x4,
	};

	enum
	{
		E_SUCESS_STATE    = 0,
		E_WRITE_STATE     = 1,
		E_RELEASE_STATE   = 2,
	};

#define E_CONNECT_CLOSE   0x7fffffff
#define E_DECODE          0x7ffffffe
#define E_SOCKET          0x7ffffffd
#define E_CONNECT_TIMEOUT 0x7ffffffc

	inline const char * net_err_2_str(int err_code)
	{
		err_code = - err_code;

		switch (err_code)
		{
			case E_CONNECT_CLOSE:
				return "E_CONNECT_CLOSE";
			case E_DECODE:
				return "E_DECODE";
			case E_SOCKET:
				return "E_SOCKET";
			case E_CONNECT_TIMEOUT:
				return "E_CONNECT_TIMEOUT";

			default:
				{
					break;
				}
		}

		return ::strerror(err_code);
	}

	//// ----------- define function ----------------
#define SAFE_DELETE(ptr) \
	if (ptr) \
	{ \
		delete ptr; \
		ptr  = 0; \
	}

#define SAFE_DELETE_ARR(arr) \
	if (arr) \
	{ \
		delete [] arr; \
		arr = 0; \
	}

#define SAFE_DELETE_VEC SAFE_DELETE_ARR

#define MIN(a, b) ((a) > (b)? (b): (a))

#define MAX(a, b) ((a) > (b)? (a): (b))

#define DECL_BASE_VAR(var, type) \
	type _##var; \
	type var() const { return _##var; } \
	void var(type val) { _##var = val; }

#define DECL_USER_VAR(var, type) \
	type _##var; \
	const type & var() const { return _##var; } \
	void var(const type & val) { _##var = val; }

	typedef uint16_t STRLEN;

#define str_sizeof(str) (sizeof(STRLEN) + str.size())

	//// ----------- define function ----------------

	//// ------------ byte -----------------------

#define make_uint16(b1, b0) \
	((((uint16_t)(uint8_t)b1) << 8) | ((uint16_t)(uint8_t)b0))

#define make_uint32(b3, b2, b1, b0) \
	((((uint32_t)make_uint16(b3, b2)) << 16) | ((uint32_t)make_uint16(b1, b0)))

#define make_uint64(b7, b6, b5, b4, b3, b2, b1, b0) \
	((((uint64_t)make_uint32(b7, b6, b5, b4)) << 32) | ((uint64_t)make_uint32(b3, b2, b1, b0)))

	//// ------------ byte -----------------------

	//// ------------- typedef ---------------------

	typedef char byte;
	typedef unsigned char ubyte;

	//// ------------- typedef ---------------------

	//// -----------inline function ----------------
	inline int32_t self_or_max(int32_t val)
	{
		return ((val >= 0)? val: 0x7fffffff);
	}

	//// -----------inline function ----------------

	template <uint16_t _H, uint16_t _L> 
		struct MakeUint32_t
		{   
			enum { value = ((((uint32_t)_H) << 16) | ((uint32_t)_L)) };
		};  
}

//// ------------- LOGGER ----------------------

#ifdef _LOG4CPLUS

#include <log4cplus/logger.h>
#include <log4cplus/loggingmacros.h>
#include <log4cplus/configurator.h>

#define DECL_LOGGER(logger)  static log4cplus::Logger logger;

#define IMPL_LOGGER(classname, logger)  \
	log4cplus::Logger classname::logger = log4cplus::Logger::getInstance(#classname);

#define DECL_LOGGER_TMPL_1(logger) static log4cplus::Logger logger;

#define IMPL_LOGGER_TMPL_1(classname, logger) \
	template <typename _T> \
log4cplus::Logger classname<_T>::logger = log4cplus::Logger::getInstance(#classname);

#define DECL_LOGGER_TMPL_2(logger) static log4cplus::Logger logger;

#define IMPL_LOGGER_TMPL_2(classname, logger) \
	template <typename _T1, typename _T2> \
log4cplus::Logger classname<_T1, _T2>::logger = log4cplus::Logger::getInstance(#classname);

#endif

//// ------------- LOGGER ----------------------

namespace __gnu_cxx
{
	template <>
		struct hash<std::string>
		{
			size_t operator () (const std::string & key) const
			{
				return __stl_hash_string(key.c_str());
			}
		};

#if __WORDSIZE != 64
	template <>
		struct hash<uint64_t>
		{
			size_t operator () (uint64_t key) const
			{
				return (size_t)key;
			}
		};
#endif
};

#endif

